package com.hwtx.form.domain.handle;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.LongNode;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.hwtx.form.annotation.*;
import com.hwtx.form.domain.def.FormDef;
import com.hwtx.form.domain.def.OrgTreeOption;
import com.hwtx.form.domain.service.OrgService;
import com.hwtx.form.domain.service.RacService;
import com.hwtx.form.domain.vo.FormData;
import com.hwtx.form.domain.vo.FormListVo;
import com.hwtx.form.domain.vo.FormRepData;
import com.hwtx.form.dto.FormListQuery;
import com.hwtx.form.query.FormValueQuery;
import io.geekidea.boot.common.constant.SystemConstant;
import io.geekidea.boot.system.entity.SysOrg;
import io.geekidea.boot.system.entity.SysOrgRole;
import io.geekidea.boot.system.entity.SysOrgUser;
import io.geekidea.boot.system.query.OrgQuery;
import io.geekidea.boot.system.vo.OrgTreeVo;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cglib.beans.BeanMap;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.hwtx.form.domain.FormConstants.*;
import static com.hwtx.form.util.JacksonUtil.addArrayValue;
import static com.hwtx.form.util.JacksonUtil.map2Oject;

@FormType(ORG_FORM_HANDLE_NAME)
@FormId(ORG_ROLE_FORM_ID)
@Slf4j
public class OrgFormHandle implements FormDataHandle, FormDefHandle {

    @Resource
    private OrgService orgService;
    @Resource
    private RacService racService;

    @Action
    @Log(type = OperationType.UPDATE, value = "机构分配角色")
    public boolean assignRoles(Map<String, Object> formData) {
        String orgId = (String) formData.get("orgId");
        String roles = (String) formData.get("roles");
        if (StringUtils.isNotEmpty(roles)) {
            List<SysOrgRole> orgRoles = Arrays.stream(roles.split(",")).map(id -> {
                SysOrgRole sysOrgRole = new SysOrgRole();
                sysOrgRole.setOrgId(Long.valueOf(orgId));
                sysOrgRole.setRoleId(Long.valueOf(id));
                return sysOrgRole;
            }).collect(Collectors.toList());
            return racService.assignRoles(orgRoles);
        }
        return true;
    }

    @Action
    @Log(type = OperationType.UPDATE, value = "机构解绑用户")
    public boolean unAssignUsers(Map<String, Object> formData) {
        String orgId = (String) formData.get("orgId");
        String userId = (String) formData.get("userId");
        if (StringUtils.isEmpty(orgId) || StringUtils.isEmpty(userId)) {
            log.error("orgId or userId is empty");
            return false;
        }
        return racService.unBindOrgUsers(Lists.newArrayList(createSysOrgUser(orgId, userId)));
    }

    @Action
    @Log(type = OperationType.UPDATE, value = "机构分配用户")
    public boolean assignUsers(Map<String, Object> formData) {
        String orgIdStr = (String) formData.get("orgIds");
        List<String> orgIds = null;
        if (StringUtils.isNotEmpty(orgIdStr)) {
            orgIds = Splitter.on(",").splitToList(orgIdStr);
        }
        String userStr = (String) formData.get("userIds");
        List<String> userIds = null;
        if (StringUtils.isNotEmpty(userStr)) {
            userIds = Splitter.on(",").splitToList(userStr);
        }
        if (CollectionUtils.isEmpty(orgIds) || CollectionUtils.isEmpty(userIds)) {
            log.error("orgIds or userIds is empty");
            return false;
        }
        for (String orgId : orgIds) {
            racService.bindOrgUsers(userIds.stream().map(id -> createSysOrgUser(orgId, id)).collect(Collectors.toList()));
        }
        return true;
    }

    private SysOrgUser createSysOrgUser(String orgId, String userId) {
        SysOrgUser sysOrgUser = new SysOrgUser();
        sysOrgUser.setOrgId(Long.valueOf(orgId));
        sysOrgUser.setUserId(Long.valueOf(userId));
        return sysOrgUser;
    }

    @Override
    public FormListVo<?> query(FormDef formDef, FormListQuery formListQuery) {
        String[] name = formListQuery.getSearchData().get("name");
        String orgName = null;
        if (name != null && name.length > 0) {
            orgName = name[0];
        }
        List<SysOrg> treeData = orgService.getOrgs(OrgQuery.builder().name(orgName).build());
        if (Objects.equals(formListQuery.getRetType(), RET_TYPE_LIST)) {
            FormListVo<OrgTreeVo> formListVo = new FormListVo<>();
            formListVo.setRows(orgService.getOrgTree(SystemConstant.ROOT_MENU_ID, treeData));
            formListVo.setCount(treeData.size());
            return formListVo;
        } else {
            FormListVo<OrgTreeOption> formListVo = new FormListVo<>();
            formListVo.setRows(orgService.getTreeOption(SystemConstant.ROOT_MENU_ID, treeData));
            return formListVo;
        }
    }

    @Override
    public FormRepData getFormData(FormDef formDef, FormValueQuery formValueQuery) {
        SysOrg sysOrg = orgService.getOrgById(formValueQuery.getValueIds().getFirst());
        return FormRepData.builder().data(BeanMap.create(sysOrg)).build();
    }

    @Override
    public Object saveFormData(FormDef formDef, FormData formData) {
        SysOrg sysOrg = map2Oject(formData.getData(), SysOrg.class);
        assert sysOrg != null;
        if (sysOrg.getId() == null) {
            if (sysOrg.getParentId() == null) {
                Map<String, String> parentInfo = (Map<String, String>) formData.getData().get("parent.dir");
                if (parentInfo != null) {
                    String pId = parentInfo.get("value");
                    if (StringUtils.isNotEmpty(pId)) {
                        sysOrg.setParentId(Long.valueOf(pId));
                    }
                }
            }
            return orgService.addOrg(sysOrg);
        } else {
            return orgService.updateOrg(sysOrg);
        }
    }

    @Override
    public Object removeFormData(FormDef formDef, FormValueQuery formValueQuery) {
        if (CollectionUtils.isNotEmpty(formValueQuery.getValueIds())) {
            return orgService.deleteOrg(formValueQuery.getValueIds().getFirst());
        }
        return false;
    }

    @Override
    public void handleDefContent(FormDef formDef, JsonNode content, Map<String, String[]> formDefQuery) {
        String[] orgIds = formDefQuery.get("orgId");
        if (orgIds != null && orgIds.length > 0) {
            String orgId = orgIds[0];
            List<SysOrgRole> orgRoles = racService.getRolesByOrgId(Long.valueOf(orgId));
            if (CollectionUtils.isNotEmpty(orgRoles)) {
                addArrayValue(content, "rowSelection", "selectedRowKeys", orgRoles.stream().map(orgRole -> new LongNode(orgRole.getRoleId())).collect(Collectors.toList()));
            }
        }
    }
}
